package com.michael.xx.audiorecoder.encoder;

import com.michael.xx.audiorecoder.AudioFileUtils;
import com.michael.xx.audiorecoder.Mp3OutputStream;

import net.sourceforge.lame.java.AudioSystem;
import net.sourceforge.lame.java.LameAudioFormat;
import net.sourceforge.lame.lowlevel.LameEncoder;
import net.sourceforge.lame.mp3.Lame;
import net.sourceforge.lame.mp3.MPEGMode;

import java.io.FileNotFoundException;
import java.io.IOException;

public class Mp3Encoder extends AudioEncoder {

    //---- Constants

    private static final boolean USE_VARIABLE_BITRATE = false;
    private static final int GOOD_QUALITY_BITRATE = 256;

    private static final String MP3_MAGIC_NUMBER = "FF FB";
    private static final int MP3_TRACK_LENGTH = 198477;

    Mp3OutputStream fileOutputStream = null;

    LameEncoder encoder;
    private Mp3OutputStream mSingleChannelOutputStream;

    @Override
    public void init(int sampleRate, int sampleSizeInBits, int channelCount) {
        super.init(sampleRate, sampleSizeInBits, channelCount);
        destinationFile = AudioFileUtils.getMP3FileAbsolutePath(System.currentTimeMillis() + "");
        LameAudioFormat audioFormat = new LameAudioFormat(
                LameAudioFormat.Encoding.PCM_SIGNED,
                sampleRate,
                sampleSizeInBits, channelCount,
                AudioSystem.NOT_SPECIFIED,
                AudioSystem.NOT_SPECIFIED,
                false
        );
        encoder = new LameEncoder(audioFormat, 128, MPEGMode.STEREO, Lame.QUALITY_HIGHEST,
                USE_VARIABLE_BITRATE);
        try {
            fileOutputStream = new Mp3OutputStream(getDestFile());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
//        try {
//            mSingleChannelOutputStream = new Mp3OutputStream(AudioFileUtils.getMP3FileAbsolutePath("single_channel"));
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }
//        singleChannelBuffer = null;
    }

    byte[] singleChannelBuffer;

    @Override
    public void encodeBuffer(byte[] inputBuffer, int pcmOffset, int readSize, byte[] outputBuffer) {
        if (singleChannelBuffer == null) {
            singleChannelBuffer = new byte[outputBuffer.length / 2];
        }
        int bytesWritten = encoder.encodeBuffer(inputBuffer, 0, readSize, outputBuffer);
        fileOutputStream.write(outputBuffer, 0, bytesWritten);
    }

    @Override
    public void close() {
        if (encoder != null) {
            encoder.close();
        }
        try {
            if (fileOutputStream != null) {
                fileOutputStream.flush();
                fileOutputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if (mSingleChannelOutputStream != null) {
                mSingleChannelOutputStream.flush();
                mSingleChannelOutputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
